﻿using System;
using System.Linq;
using System.Reflection;
using Autodesk.AutoCAD.ApplicationServices;

namespace AutoCADDotNetLibrary
{
    /// <summary>
    /// <see cref="Autodesk.AutoCAD.Runtime.IExtensionApplication"/>的帮助类
    /// </summary>
    public static class ExtensionApplication
    {
        private static void InvokeMethod<T>(Assembly assembly) where T : InvokeMethodAttribute
        {
            var methods = assembly.GetTypes().SelectMany(x => x.GetMethods()
                        .Select(y => new { Method = y, Att = y.GetCustomAttributes(false).OfType<T>().ToArray() }))
                        .Where(x => x.Att.Length != 0).OrderBy(x => x.Att[0].Index).ToList();

            //不能同时运行2个派生类 InvokeMethodAttribute
            var first = methods.FirstOrDefault(x => x.Att.Length != 1);
            if (first != null)
            {
#if DEBUG
                System.Diagnostics.Debugger.Break();
#endif
                //使用throw new Exception()没有反应
                Application.DocumentManager.MdiActiveDocument?.Editor?.WriteMessage($"\n错误：{first.Method.DeclaringType.FullName}.{first.Method.Name}重复使用了{nameof(T)}及其派生类。\n");
                return;
            }

            //有IsDebug=true时，测试IsDebug为真的方法
            if (methods.Any(x => x.Att.First().IsDebug))
            {
                methods = methods.Where(x => x.Att.First().IsDebug).ToList();
            }

            foreach (var method in methods)
            {
#pragma warning disable CS0168 // 声明了变量，但从未使用过
                try
                {
                    method.Att.First().InvokeMethod(method.Method);
                }
                catch (Exception ex)
                {
#if DEBUG
                    System.Diagnostics.Debugger.Break();
#endif
                }
#pragma warning restore CS0168 // 声明了变量，但从未使用过
            }
        }

        /// <summary>
        /// 运行程序集中具有<see cref="InitializeAttribute"/>的公有方法和公有静态函数
        /// </summary>
        /// <param name="assembly">程序集</param>
        public static void Initialize(Assembly assembly)
        {
            InvokeMethod<InitializeAttribute>(assembly);
        }

        /// <summary>
        /// 运行程序集中具有<see cref="TerminateAttribute"/>的公有方法和公有静态函数
        /// </summary>
        /// <param name="assembly">程序集</param>
        public static void Terminate(Assembly assembly = null)
        {
            InvokeMethod<TerminateAttribute>(assembly);
        }
    }
}
